package com.xxxtea.util;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import lombok.Cleanup;
import lombok.experimental.UtilityClass;
import org.objenesis.strategy.StdInstantiatorStrategy;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;

/**
 * Kryo序列化工具类
 * 
 * 基于Kryo框架提供的高性能Java对象序列化和反序列化功能，包括：
 * - 对象序列化：将Java对象序列化为字节流并保存到文件
 * - 对象反序列化：从文件中读取字节流并反序列化为Java对象
 * - 高性能：Kryo是一个快速、高效的序列化框架
 * 
 * 主要特性：
 * - 支持循环引用处理
 * - 无需显式注册类
 * - 无需无参构造函数
 * - 自动资源管理
 * 
 * @author badman
 * @since 1.0.0
 */
@UtilityClass
public class KryoSerializer {
	
	/**
	 * Kryo实例
	 * 用于执行序列化和反序列化操作
	 */
	private final Kryo kryo = new Kryo();

	/**
	 * 静态初始化块：配置Kryo序列化器
	 * 设置序列化策略和参数
	 */
	static {
		// 启用循环引用支持：避免对象间循环引用导致的序列化问题
		kryo.setReferences(true);
		
		// 禁用类注册要求：无需显式注册要序列化的类
		kryo.setRegistrationRequired(false);
		
		// 设置实例化策略：使用标准实例化策略，无需无参构造函数
		kryo.setInstantiatorStrategy(new StdInstantiatorStrategy());
	}

	/**
	 * 从文件中读取并反序列化对象
	 * 
	 * 使用@Cleanup注解自动管理输入流资源
	 * 
	 * @param file 包含序列化数据的文件
	 * @param <T> 目标对象类型
	 * @return 反序列化后的对象
	 * @throws IOException 文件读取异常
	 */
	@SuppressWarnings("unchecked")
	public <T> T readObject(File file) throws IOException {
		// 创建输入流并自动管理资源
		@Cleanup Input input = new Input(Files.newInputStream(file.toPath()));
		
		// 读取类信息和对象数据，并反序列化
		return (T) kryo.readClassAndObject(input);
	}

	/**
	 * 将对象序列化并写入文件
	 * 
	 * 使用@Cleanup注解自动管理输出流资源
	 * 
	 * @param file 目标文件
	 * @param object 要序列化的对象
	 * @throws IOException 文件写入异常
	 */
	public void writeObject(File file, Object object) throws IOException {
		// 创建输出流并自动管理资源
		@Cleanup Output output = new Output(Files.newOutputStream(file.toPath()));
		
		// 写入类信息和对象数据
		kryo.writeClassAndObject(output, object);
		
		// 刷新输出流，确保数据写入文件
		output.flush();
	}
}
